////////////////////////////////////////////////////////////////////////////////
//
//  MICROSOFT CORPORATION
//  Copyright (c) Microsoft Corporation.
//  All Rights Reserved.
//
//  NOTICE: Microsoft Confidential. Intended for Internal Use Only.
//
////////////////////////////////////////////////////////////////////////////////

package com.msn.beet.tracking.atlas
{

import com.msn.beet.logging.Log;
import com.msn.beet.tracking.ITrackModel;

import flash.external.ExternalInterface;

/**
 * Extracts search keywords and search engine name from referrer string,
 * sends track to Atlas. Supports manually passing the referrer string in
 * the constructor, if script access is disabled, or will attempt to access
 * document.referrer from JS.
 *
 */
public class AtlasRefererAction extends AtlasTrackAction
{
    include "../../core/Version.as";

    protected static const SEND_REFERER:String = "sendReferer";

    protected var refererDomain:String;
    protected var refererName:String;
    protected var referer:String;
    protected var searchParams:String;

    /** mapping of search engine keyword parameters        */
    protected var searchEngines:Object = {};

    public function AtlasRefererAction(searchEngines:XML,
                                       referer:String = null):void
    {
        super(null, SEND_REFERER);
        populateSearchEngines(searchEngines);
        this.referer = referer || this.refererFromJS;
    }

    override public function parseForAtlas(trackModel:ITrackModel):String
    {
        var model:AtlasModel = trackModel as AtlasModel;
        var track:String = null;

        if (referer.indexOf("http://") != -1)
        {
            populateRefererInfo();

            track = model.baseString +
                join(model.location, "location") +
                join("view", "action") +
                join(refererName, "search") +
                join(searchParams, "keywords") +
                join(refererDomain, "domain") +
                join(referer, "url") +
                "?" + Math.random();
        }
        return track;
    }

    /** Unsupported method, use Atlas.  */
    override public function parseForAtlasJS(pModel:ITrackModel):String
    {
        Log.warn("Unsupported method: AtlasRefererAction/" +
                "parseForAtlasJS(). Use AtlasSneder or Atlas.js to send " +
                "referrer track");
        return null;
    }

    /** Populate page referer information, extract keywords.    */
    protected function populateRefererInfo():void
    {
        var refererKey:String = null;
        this.refererDomain = referer.split("/")[2];

        // get parameter name for search engine keywords
        for (var p:Object in this.searchEngines)
        {
            // if there is a matching key
            if (this.refererDomain.lastIndexOf(p as String) != -1)
            {
                // save matching search engine name
                this.refererName = p as String;
                // get the key
                refererKey = this.searchEngines[p];
            }
        }

        // extract keywords
        var params:Array /* of Object */ = this.referer.split(refererKey);
        // split off tail of string
        this.searchParams = params[1].split("&")[0];
        // format for atlas [replace + with ,]
        this.searchParams = this.searchParams.replace(/\+/g, ",");
    }

    /**
     * Creates lookup table for mapping search engine name to keyword
     * identifier.
     * @example
     <listing version="3.0">
        &lt;searchEngines&gt;
            &lt;!--&lt;searchEngineName
                paramKey="keywordIdentifier=" /&gt; --&gt;
            &lt;live paramKey="q=" /&gt;
            &lt;google paramKey="q=" /&gt;
            &lt;yahoo paramKey="p=" /&gt;
            &lt;ask paramKey="q=" /&gt;
            &lt;baidu paramKey="wd=" /&gt;
        &lt;/searchEngines&gt;
     </listing>
    */
    protected function populateSearchEngines(searchEnginesXML:XML):void
    {
        if (searchEnginesXML.name() != "searchEngines")
        {
            var msg:String = "Incorrect search engines xml \n" +
                    "com.msn.beet.tracking.atlas.actions." +
                    "AtlasRefererAction/populateSE()";
            throw new ArgumentError(msg);
        }

        var list:XMLList = searchEnginesXML.children();

        for (var p:String in list)
        {
            this.searchEngines[list[p].name()] = list[p].@paramKey;
        }
    }

    protected function get refererFromJS():String
    {
        if (ExternalInterface.available)
        {
            return ExternalInterface.call(
                "function(){ return document.referrer }");
        }
        else
        {
            return "";
        }
    }

}

}
